package org.jeecg.modules.demo.mes.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.modules.demo.mes.entity.MesMaterial;
import org.jeecg.modules.demo.mes.entity.MesMaterialDetail;
import org.jeecg.modules.demo.mes.mapper.MesMaterialMapper;
import org.jeecg.modules.demo.mes.service.IMesMaterialDetailsService;
import org.jeecg.modules.demo.mes.service.IMesMaterialService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 物料表
 * @Author: jeecg-boot
 * @Date: 2022-10-27
 * @Version: V1.0
 */
@Service
public class MesMaterialServiceImpl extends ServiceImpl<MesMaterialMapper, MesMaterial> implements IMesMaterialService {

    @Autowired
    private IMesMaterialDetailsService mesMaterialDetailsService;

    /**
     * 保存物料
     */
    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
    public void saveMesMaterial(MesMaterial mesMaterial, String loginName) throws JeecgBootException {
        final Date now = new Date();
        mesMaterial.setUpdateBy(loginName);
        mesMaterial.setUpdateTime(now);
        //保存主表
        super.save(mesMaterial);
        //保存物料表之前，先保存附表
        final String materialSequence = mesMaterial.getMaterialSequence();
        final Integer materialNumber = mesMaterial.getMaterialNumber();
        if (materialNumber != null && StringUtils.isNotBlank(materialSequence)) {
            final List<MesMaterialDetail> detailsList = new ArrayList<>();
            for (int i = 0; i < materialNumber; i++) {
                final MesMaterialDetail details = new MesMaterialDetail();
//                details.setId(UUID.randomUUID().toString().replace("-",""));
                details.setCreateBy(loginName);
                details.setCreateTime(now);
                details.setUpdateBy(loginName);
                details.setUpdateTime(now);
                details.setMainId(mesMaterial.getId());
                details.setMaterialStatus("1");
                details.setMaterialBarCode(materialSequence + String.format("%03d", i));
                detailsList.add(details);
            }
            mesMaterialDetailsService.saveBatch(detailsList);
        }

    }

    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
    public void updateMesMaterialById(MesMaterial mesMaterial) throws JeecgBootException {
        final String id = mesMaterial.getId();
        if (StringUtils.isBlank(id)) {
            return;
        }

        updateMesMaterialDetailsByMainId(mesMaterial);
        //修改物料表
        this.updateById(mesMaterial);
    }

    /**
     * 同步更新物料详情表中的数据
     */
    private void updateMesMaterialDetailsByMainId(MesMaterial mesMaterial) {
        //1. 针对条码进行更新操作
        final String mainId = mesMaterial.getId();
        final String materialSequence = mesMaterial.getMaterialSequence();
        final Integer materialNumber = mesMaterial.getMaterialNumber();
        final Map<String, Object> cxMap = new HashMap<>();
        cxMap.put("mainId", mainId);
        final List<MesMaterialDetail> list = mesMaterialDetailsService.queryMaterialDetailsSelective(cxMap);
        if (list == null || list.size() == 0) {
            return;
        }
        final int size = list.size();
        //判断是否是修改的物料号
        final MesMaterial mesMaterialFromDB = this.getById(mainId);
        if (!StringUtils.equals(mesMaterial.getMaterialSequence(), mesMaterialFromDB.getMaterialSequence())) {
            //说明编辑了物料号，需要同步更新详情表中的数据
            for (MesMaterialDetail details : list) {
                final String materialBarCode = details.getMaterialBarCode();
                details.setMaterialBarCode(materialSequence + materialBarCode.substring(materialBarCode.length() - 3));
            }
            mesMaterialDetailsService.updateBatchById(list);
        }

        //2. 针对数量进行增删操作
        if (materialNumber > size) {
            //新修改的数量大于现存的，需要新增
            for (int i = size; i < materialNumber; i++) {
                addNewDetail(mainId, i, materialSequence);
            }
        } else if (materialNumber < size) {
            //去除未使用的物料条码集合
            final List<String> ids = list.stream().filter(item -> StringUtils.equals("1", item.getMaterialStatus())).map(MesMaterialDetail::getId).collect(Collectors.toList());
            if (ids.size() == 0) {
                return;
            }
            //已使用数量
            final int usedCount = size - ids.size();
            mesMaterialDetailsService.removeByIds(ids);
            //新增差值
            for (int i = usedCount; i < materialNumber; i++) {
                addNewDetail(mainId, i, materialSequence);
            }
        }

    }

    /**
     * 新增默认物料条码
     *
     * @param mainId           主表id
     * @param seq             条码
     * @param materialSequence 物料编码
     */
    private void addNewDetail(String mainId, int seq, String materialSequence) {
        final MesMaterialDetail mesMaterialDetail = new MesMaterialDetail();
        mesMaterialDetail.setMaterialStatus("1");
        mesMaterialDetail.setMainId(mainId);
        mesMaterialDetail.setMaterialBarCode(materialSequence + String.format("%03d", seq));
        final String userName = JwtUtil.getUserName();
        mesMaterialDetail.setCreateBy(userName);
        mesMaterialDetail.setCreateTime(new Date());
        mesMaterialDetail.setUpdateBy(userName);
        mesMaterialDetail.setUpdateTime(new Date());
        mesMaterialDetailsService.save(mesMaterialDetail);
    }

    /**
     * 通用物料表查询
     */
    @Override
    public List<MesMaterial> queryMesMaterialsSelective(Map<String, Object> cxMap) throws JeecgBootException {
        return this.baseMapper.queryMesMaterialsSelective(cxMap);
    }

    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
    public void removeMesMaterialById(String id) throws JeecgBootException {
        this.removeById(id);
        mesMaterialDetailsService.removeByMainId(id);
    }
}
